#include "Engine.h"
#include "Input.h"
#include "GameState.h"
#include <time.h>
#include "LuaManager.h"
#include "BPhysicsActor.h"
#include "ResourceManager.h"
#include "Server.h"
#include "GameMessageFactory.h"
#include "Timer.h"
#include "Client.h"
#include "ServerState.h"
#include "ClientState.h"
#include "LineDrawer.h"
#include "LoadState.h"

/************************************************************************/
/*General windows message handling function GLOBAL                      */
/************************************************************************/
LRESULT WINAPI WindowsMessageProcedure( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    if(TwEventWin(hWnd, msg, wParam, lParam))
        return 0;
    switch( msg )
    {
    case WM_SYSCOMMAND:
        {
            switch (wParam)
            {
            case SC_SCREENSAVE:					// Screen saver trying to start ?
            case SC_MONITORPOWER:				// Monitor trying to enter power save ?
                return 0;	
            }
            break;
        }
    case WM_DESTROY:
        {
            PostQuitMessage( 0 );
            Engine::Instance()->Quit();
            return 0;
            break;
        }
    case WM_CLOSE:
        {
            PostQuitMessage(0);
            Engine::Instance()->Quit();
            return 0;
            break;
        }
    case WM_MOUSEMOVE:
        {
            Engine::Instance()->SetMousePosition(LOWORD(lParam),HIWORD(lParam));
            break;
        }
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

LuaPlus::LuaObject* Engine::Static_MetaTable = 0;
LuaPlus::LuaObject* Engine::StaticInitializeLuaMetaTable()
{
    Static_MetaTable = new LuaPlus::LuaObject;
    *Static_MetaTable = LuaManager::Instance()->GetOwner()->GetGlobals().CreateTable("EngineTable");
    Static_MetaTable->SetObject("__index", *Static_MetaTable);
    LUA_REGISTER("Quit", Engine, &Engine::Quit);
    LUA_REGISTER("CreateWindowClass", Engine, &Engine::CreateWindowClass);
    LUA_REGISTER("CreateWindowObj", Engine, &Engine::CreateWindowObj);
    LUA_REGISTER("CreateDevice", Engine, &Engine::CreateDevice);
    LUA_REGISTER("InitializeDepthSurface", Engine, &Engine::InitializeDepthSurface);
    LUA_REGISTER("InitializeInput", Engine, &Engine::InitializeInput);
    LUA_REGISTER("ShutDownInput", Engine, &Engine::ShutDownInput);
    LUA_REGISTER("LoseDevice", Engine, &Engine::LoseDevice);
    LUA_REGISTER("LoadAndSetDefaultTexture", Engine, &Engine::LoadAndSetDefaultTexture);
    LUA_REGISTER("PrintLuaMessage", Engine, &Engine::PrintLuaMessage);
    LUA_REGISTER("LOpenLuaFile", Engine, &Engine::LOpenLuaFile);
    LUA_REGISTER("LLoadSharedMesh", Engine, &Engine::LLoadSharedMesh);
    LUA_REGISTER("LLoadTexture", Engine, &Engine::LLoadTexture);
    LUA_REGISTER("ReleaseLuaTables", Engine, &Engine::ReleaseLuaTables);
    LUA_REGISTER("ReleaseResources", Engine, &Engine::ReleaseResources);
    LUA_REGISTER("EndCurrentState", Engine, &Engine::EndCurrentState);
    LUA_REGISTER("Unregister", Engine, &Engine::Unregister);
    return Static_MetaTable;
}
Engine::Engine()
{
    m_isDeviceVSYNC = false;
    m_time = 0.0f;
    m_lineDrawer = NULL;
    m_resourceManager = NULL;
    m_mousePosition[0] = m_mousePosition[1] = 0;
    m_screenSize[0] = m_screenSize[1] = 0;
    m_clock = NULL;
    m_lastFrameDt = 0;
    m_frameCounter = 0;
    m_frameDisplay = 0;
    m_depthStencilSurface = NULL;
    m_oldDepthStencilSurface = NULL;
    m_oldRenderTarget = NULL;
    m_mainD3DDevice = NULL;
    m_running = true;
    m_currentState = 0;
    m_requestState = 0;
}
int Engine::Execute()
{
    if(!Initialise())
    {
        CleanUp();
        return -1;
    }

    MSG msg;
    memset(&msg, 0, sizeof(MSG));
    while(m_running)
    {   
        m_clock->reset();
        if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        ++m_frameCounter;
        Input::Instance()->Process();
        ManageStates();
        Update();
        Draw();
        m_time += m_lastFrameDt;
        if(m_time > 1000)
        {
            m_frameDisplay = m_frameCounter;
            m_frameCounter = 0;
            m_time = 0;
        }
        /* FrameRate */
        m_lastFrameDt = m_clock->getTimeMilliseconds();
    }

    CleanUp();
    return 0;
}
bool Engine::Initialise()
{
    // Seed the random-number generator with the current time 
    // so that the numbers will be different every time we run.
    srand( (unsigned)time( NULL ) );
    //new ourselves a clock
    m_clock = new btClock;

    //new a manager
    m_resourceManager = new ResourceManager;

    //init the manager, and create and store the meta table data
    TEST_IF(LuaManager::Instance()->Initialize());

    m_staticLuaObjects.push_back(BPhysicsActor::StaticInitializeLuaMetaTable());
    m_staticLuaObjects.push_back(Audio_Engine::AudioManager::StaticInitializeLuaMetaTable());
    m_staticLuaObjects.push_back(Engine::StaticInitializeLuaMetaTable());
    // DO SAME FOR ALL GAMESTATES HERE 
    m_staticLuaObjects.push_back(ServerState::StaticInitializeLuaMetaTable());
    m_staticLuaObjects.push_back(ClientState::StaticInitializeLuaMetaTable());

    //Cast the engine instance to a pointer, and set its table
    LuaPlus::LuaObject owner = LuaManager::Instance()->GetOwner()->BoxPointer(this);
    owner.SetMetaTable(*Static_MetaTable);
    //run the start up file
    if(!LuaManager::Instance()->OpenFile("../src/Scripts/engine.lua"))  //in the IDE
        if(!LuaManager::Instance()->OpenFile("Scripts/engine.lua"))     //in a distro
            return false;

    //Get the instance of the game in the LUA file
    LuaPlus::LuaObject state = LuaManager::Instance()->GetOwner()->GetGlobal("TheEngine");
    if(state.IsTable())
    {
        //call Start on the game object
        if(state["Start"].IsFunction())
        {
            LuaPlus::LuaFunction<void> start = state["Start"];
            start(owner);
        }
    }
    //Registers the vertex declaration
    CustomVertex::RegisterDeclarations();
    DebugVert::RegisterDeclarations();

    //init stuff for the UI
    TEST_IF(TwInit(TW_DIRECT3D9, m_mainD3DDevice));

    m_lineDrawer = new LineDrawer;
    m_lineDrawer->Initialize();
    m_lineDrawer->setDebugMode(1);

    m_currentState = new LoadState;
    m_currentState->Initialise();
    m_currentState->m_initialised = true;
    return true;
}
void Engine::Update()
{
    // Allows you to hit escape to exit
    if( Input::Instance()->GetKeyboard().GetKey(DIK_ESCAPE) == KeyState_Pressed)
    {
        Quit();
    }
    m_currentState->Update(m_lastFrameDt);
}
void Engine::Draw()
{
    m_currentState->Draw();
    if(m_lineDrawer)
        m_lineDrawer->ClearTempLines();
}
void Engine::CleanUp()
{
    //Get the instance of the game in the LUA file
    LuaPlus::LuaObject state = LuaManager::Instance()->GetOwner()->GetGlobal("TheEngine");
    if(state.IsTable())
    {
        //call Start on the game object
        if(state["ShutDown"].IsFunction())
        {
            LuaPlus::LuaFunction<void> stop = state["ShutDown"];
            stop();
        }
    }

    if(CustomVertex::s_dcl)
        CustomVertex::Release();
    if(DebugVert::s_dcl)
        DebugVert::Release();

    TwTerminate();

}
void Engine::Quit()
{
    m_running = false;
}
void Engine::ChangeState(GameState* gs)
{
    delete m_currentState;
    m_currentState = gs;
}
void Engine::RequestChange(GameState* gs)
{
    //only changes state at start of main loop
    m_requestState = gs;
}
void Engine::ManageStates()
{
    //if there is a request state pending
    if(m_requestState != 0)
    {
        //and it is not initialised
        if ( !m_requestState->IsInitialised())
        {		
            //clean up the old state
            m_currentState->CleanUp();
            
            //change the state
            ChangeState(m_requestState);
            m_requestState = 0;

            //initialise the new state,
            m_currentState->Initialise();
            m_currentState->m_initialised = true;

        }
        else
        {
            //as above, without the initialise.
            m_currentState->CleanUp();
            ChangeState(m_requestState);
            m_requestState->OnResume();
            m_requestState = 0;
        }

    }
}
void Engine::Error(const std::string& line, const std::string& file, std::string* extras)
{
    std::string s = "Error, HRESULT returned false at line: ";
    s += line;
    s += " In file : ";
    s += file;
    if(extras)
    {
        s += " because : ";
        s += *extras;
    }
    const char* t = TwGetLastError();
    const char* e = s.c_str();
    LPCWSTR err = StringToString(e);
    MessageBox(m_hWindow, err, NULL, 0);
}
LPCTSTR Engine::StringToString( const char *p )
{
    short* a = new short[strlen(p)+1];

    for(unsigned int i = 0; i <strlen(p);i++)
    {
        a[i] = p[i];
    }

    a[strlen(p)] = NULL;

    return (LPCTSTR)a;
}
void Engine::StringToString(short* buffer, const char *p )
{
    for(unsigned int i = 0; i <strlen(p);i++)
    {
        buffer[i] = p[i];
    }

    buffer[strlen(p)] = NULL;
}
void Engine::StringToString( wchar_t* buf, const char* src )
{
    for(unsigned int i = 0; i <strlen(src);i++)
    {
        buf[i] = src[i];
    }

    buf[strlen(src)] = 0;
}
void Engine::CreateWindowClass(const char* name)
{
    int numChars = strlen(name);
    m_windowNameWide = new wchar_t[numChars+1];
    m_windowName = new char[numChars];
    memset(m_windowName, 0, sizeof(char) * numChars);
    memset(m_windowNameWide, 0, sizeof(wchar_t) * numChars+1);
    memcpy(m_windowName, name, sizeof(char)*numChars);
    StringToString(m_windowNameWide, name);
    m_wind.cbSize = sizeof(WNDCLASSEX);
    m_wind.style          = CS_HREDRAW | CS_VREDRAW;
    m_wind.lpfnWndProc    = WindowsMessageProcedure;
    m_wind.cbClsExtra     = 0;
    m_wind.cbWndExtra     = 0;
    m_wind.hInstance      = GetModuleHandle(NULL);
    m_wind.hIcon          = NULL;
    m_wind.hCursor        = NULL;
    m_wind.hbrBackground  = NULL;
    m_wind.lpszMenuName   = NULL;
    m_wind.lpszClassName  = m_windowNameWide;
    m_wind.hIconSm        = NULL;

    //Register the window
    RegisterClassEx(&m_wind); 

    //store the hardware instance
    m_hInstance = m_wind.hInstance;
}
void Engine::CreateWindowObj( const char* label, bool FS, int x, int y )
{
    //Create the window
    m_screenSize[0] = x; m_screenSize[1] = y;
    if(FS)
    {
        m_screenSize[0] = GetSystemMetrics(SM_CXFULLSCREEN);
        m_screenSize[1] = GetSystemMetrics(SM_CYFULLSCREEN);
    }
    wchar_t* wideLabel = new wchar_t[strlen(label)+1];
    StringToString(wideLabel, label);
    m_hWindow = CreateWindow(m_windowNameWide, wideLabel,  
    WS_SYSMENU, 
    0,0,m_screenSize[0], m_screenSize[1], NULL, NULL, m_wind.hInstance, NULL);
    delete[] wideLabel;

    //figure out the ACTUAL size of the window generated -.-
    RECT r;
    GetClientRect(m_hWindow, &r);
    m_screenSize[0] = r.right;
    m_screenSize[1] = r.bottom;

    //Initial show and update of the window
    ShowWindow(m_hWindow, SW_SHOWDEFAULT );
    UpdateWindow( m_hWindow );
}
void Engine::CreateDevice(bool vSync)
{
    // Create a D3D object.
    m_isDeviceVSYNC = vSync;
    m_tempD3DDevice = Direct3DCreate9( D3D_SDK_VERSION );

    if( m_tempD3DDevice == NULL )
    {
        assert(0);
    }

    D3DPRESENT_PARAMETERS parameters;
    ZeroMemory( &parameters, sizeof( parameters ) );
    parameters.Windowed = TRUE;
    parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    parameters.BackBufferFormat = D3DFMT_UNKNOWN;
    parameters.EnableAutoDepthStencil = TRUE;
    parameters.AutoDepthStencilFormat = D3DFMT_D16;
    if(m_isDeviceVSYNC)
    {
        /* VSYNC ON */
        parameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
    }
    else
    {
        /* VSYNC OFF */
        parameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    }

    if (m_tempD3DDevice->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWindow,
        D3DCREATE_HARDWARE_VERTEXPROCESSING,
        &parameters, &GetDevice() ) == E_FAIL)
    {
        assert(0);
    }
}
void Engine::ResetRenderTarget()
{
    //reset the stuff so we can carry on rendering as normal
    if( m_oldDepthStencilSurface )
    {
        TEST(m_mainD3DDevice->SetDepthStencilSurface( m_oldDepthStencilSurface ));
        m_oldDepthStencilSurface->Release();
    }
    if(m_oldRenderTarget)
    {
        //set the render target back to the one stored earlier
        TEST(m_mainD3DDevice->SetRenderTarget( 0, m_oldRenderTarget ));

        //we don't need this anymore
        m_oldRenderTarget->Release();
    }
}
void Engine::SetRenderTarget( IDirect3DTexture9* target,bool clear )
{
    // Store the old render target,
    m_oldRenderTarget = NULL;
    TEST(Engine::Instance()->GetDevice()->GetRenderTarget( 0, &m_oldRenderTarget ));

    // Create a new surface, set it to the level of our Shadow Texture, and set that as the
    // new render target
    LPDIRECT3DSURFACE9 oldSurface = NULL;
    TEST(target->GetSurfaceLevel( 0, &oldSurface ));
    TEST(Engine::Instance()->GetDevice()->SetRenderTarget( 0, oldSurface ));
    //This surface is no longer needed,
    oldSurface->Release();

    m_oldDepthStencilSurface = NULL;
    TEST(Engine::Instance()->GetDevice()->GetDepthStencilSurface(&m_oldDepthStencilSurface));
    TEST(Engine::Instance()->GetDevice()->SetDepthStencilSurface(m_depthStencilSurface));

    ////Clear the buffers (not as a color, or it generates false positives )
    if(clear)
        TEST(m_mainD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
        0x00000000, 1.0f, 0 ));
}
void Engine::InitializeInput()
{
    //Initialize the static input manager here
    if(!Input::Instance()->Init())
    {
        MessageBox(m_hWindow, L"Could not start up input manager", NULL, 0);
    }
}
LPDIRECT3DVERTEXBUFFER9 Engine::CreateUnitCube(int* totalVertsMade)
{
    //points on a cube, 4 triangles per face,
    int numTriangles = 24;
    int numVerts = numTriangles * 3;
    CustomVertex* vertArray = new CustomVertex[numVerts];
    //0 the data
    memset(vertArray,0, sizeof(CustomVertex) * numVerts);

    //starting with the -z face
    //tri 1
    vertArray[0] = CustomVertex(-1,1,-1, 0,0,0,  (float)1/3,0.25f); 
    vertArray[1] = CustomVertex(1,1,-1, 0,0,0,  (float)2/3,0.25f);
    vertArray[2] = CustomVertex(0,0,-1, 0,0,0,  0.5f,0.375f);
    //tri2
    vertArray[3] = vertArray[2];
    vertArray[4] = vertArray[1];
    vertArray[5] = CustomVertex(1,-1,-1, 0,0,0,  (float)2/3,0.5f);
    //tri 3
    vertArray[6] = vertArray[5];
    vertArray[7] = CustomVertex(-1,-1,-1, 0,0,0,  (float)1/3,0.5f);
    vertArray[8] = vertArray[2];
    //tri 4
    vertArray[9] = vertArray[7];
    vertArray[10] = vertArray[0];
    vertArray[11] = vertArray[2];


    // the -x face
    //tri 1
    vertArray[12] = CustomVertex(-1,1,1, 0,0,0,  0,0.25f); 
    vertArray[13] = vertArray[0];
    vertArray[14] = CustomVertex(-1,0,0, 0,0,0,  (1.0f/3.0f)/2.0f,0.375f);
    //tri2
    vertArray[15] = vertArray[14];
    vertArray[16] = vertArray[0];
    vertArray[17] = vertArray[7];
    //tri 3
    vertArray[18] = CustomVertex(-1,-1, 1, 0,0,0,  0,0.5f);
    vertArray[19] = vertArray[14];
    vertArray[20] = vertArray[7];
    //tri 4
    vertArray[21] = vertArray[18];
    vertArray[22] = vertArray[12];
    vertArray[23] = vertArray[14];

    // the +z face
    //tri 1
    vertArray[24] = CustomVertex(1,1,1, 0,0,0,  2.0f/3.0f,1); 
    vertArray[25] = CustomVertex(-1,1,1, 0,0,0, 1.0f/3.0f,1); 
    vertArray[26] = CustomVertex(0,0,1, 0,0,0,  0.5f,0.875f);
    //tri2
    vertArray[27] = vertArray[26];
    vertArray[28] = vertArray[25];
    vertArray[29] = CustomVertex(-1,-1,1, 0,0,0,  1.0f/3.0f,0.75f);
    //tri 3
    vertArray[30] = CustomVertex(1,-1, 1, 0,0,0,  2.0f/3.0f,0.75f);
    vertArray[31] = vertArray[26];
    vertArray[32] = vertArray[29];
    //tri 4
    vertArray[33] = vertArray[24];
    vertArray[34] = vertArray[26];
    vertArray[35] = vertArray[30];


    // the +x face
    //tri 1
    vertArray[36] = vertArray[1];
    vertArray[37] = CustomVertex(1,1,1, 0,0,0,  1.0f,0.25f);
    vertArray[38] = CustomVertex(1,0,0, 0,0,0,  (2.0f/3.0f)+(0.5f*(1.0f/3.0f)),0.375f);
    //tri2
    vertArray[39] = vertArray[38];
    vertArray[40] = vertArray[37];
    vertArray[41] = CustomVertex(1,-1,1, 0,0,0,  1.0f,0.5f);
    //tri 3
    vertArray[42] = vertArray[5];
    vertArray[43] = vertArray[38];
    vertArray[44] = vertArray[41];
    //tri 4
    vertArray[45] = vertArray[1];
    vertArray[46] = vertArray[38];
    vertArray[47] = vertArray[5];

    //the +y face 
    //tri 1
    vertArray[48] = CustomVertex(-1,1,1, 0,0,0,  (float)1/3,0.0f); 
    vertArray[49] = CustomVertex(1,1,1, 0,0,0,  (float)2/3,0.0f);
    vertArray[50] = CustomVertex(0,1,0, 0,0,0,  0.5f,0.125f);
    //tri2
    vertArray[51] = vertArray[50];
    vertArray[52] = vertArray[49];
    vertArray[53] = vertArray[1];
    //tri 3
    vertArray[54] = vertArray[0];
    vertArray[55] = vertArray[50];
    vertArray[56] = vertArray[1];
    //tri 4
    vertArray[57] = vertArray[48];
    vertArray[58] = vertArray[50];
    vertArray[59] = vertArray[0];

    //the -y face 
    //tri 1
    vertArray[60] = vertArray[7];
    vertArray[61] = vertArray[5];
    vertArray[62] = CustomVertex(0,-1,0, 0,0,0,  0.5f,0.625f);
    //tri2
    vertArray[63] = vertArray[62];
    vertArray[64] = vertArray[5];
    vertArray[65] = vertArray[30];
    //tri 3
    vertArray[66] = vertArray[30];
    vertArray[67] = vertArray[29];
    vertArray[68] = vertArray[62];
    //tri 4
    vertArray[69] = vertArray[7];
    vertArray[70] = vertArray[62];
    vertArray[71] = vertArray[29];
    for(int i = 0; i <numVerts; ++i)
    {
        CustomVertex v = vertArray[i];
        D3DXVECTOR3 pos(v.pos.x,v.pos.y,v.pos.z);
        D3DXVec3Normalize(&pos, &pos);
        v.normal = D3DXVECTOR4(pos,1);
        vertArray[i] = v;
    }
    //create a vertex buffer on GPU
    LPDIRECT3DVERTEXBUFFER9 texCube;
    TEST(GetDevice()->CreateVertexBuffer( numVerts*  sizeof(CustomVertex),
        D3DUSAGE_WRITEONLY, 0,
        D3DPOOL_DEFAULT , &texCube, NULL )); 

    VOID* pVertices;
    *totalVertsMade = numVerts;
    int BufferSize = sizeof( CustomVertex )* numVerts;

    texCube->Lock( 0, BufferSize, ( void** )&pVertices, 0); 

    memcpy( pVertices, vertArray, BufferSize );

    TEST(texCube->Unlock());

    delete[] vertArray;

    return texCube;
}
LPDIRECT3DVERTEXBUFFER9 Engine::CreateTexturedQuad(int* totalVertsMade)
{
    //create one in main memory
    int numVerts = 4;
    CustomVertex* vertexArray = new CustomVertex[numVerts];
    //0 the data
    memset(vertexArray,0, sizeof(CustomVertex) * numVerts);

    vertexArray[0] = CustomVertex(-1.0f,  1.0f, 0,  1,0,0, 0,0);// Top left
    vertexArray[1] = CustomVertex( 1.0f,  1.0f, 0,  1,0,0, 1,0); //top right
    vertexArray[3] = CustomVertex( 1.0f, -1.0f, 0, 1,0,0, 1,1);  //bottom right
    vertexArray[2] = CustomVertex(-1.0f, -1.0f, 0, 1,0,0, 0,1);  // bottom left

    //Create buf on GPU
    LPDIRECT3DVERTEXBUFFER9 returnBuffer;
    //create a vertex buffer on GPU
    TEST(GetDevice()->CreateVertexBuffer( numVerts * sizeof(CustomVertex),
        D3DUSAGE_WRITEONLY, 0,
        D3DPOOL_DEFAULT , &returnBuffer, NULL )); 
    VOID* pVertices;
    *totalVertsMade = numVerts;
    int BufferSize = sizeof( CustomVertex )* numVerts;

    returnBuffer->Lock( 0, BufferSize, ( void** )&pVertices, 0); 

    memcpy( pVertices, vertexArray, BufferSize );

    TEST(returnBuffer->Unlock());

    delete[] vertexArray;

    return returnBuffer;
}
void Engine::InitializeDepthSurface( int maxX, int maxY )
{
    //Has to be greater or equal to resolution of maximum render target size
    //( Which is always going to the be she shadow map, unless we use full screen textures)
    TEST( GetDevice()->CreateDepthStencilSurface( maxX, maxY,
        D3DFMT_D24X8,
        D3DMULTISAMPLE_NONE,
        0,
        TRUE,
        &m_depthStencilSurface,
        NULL ) );
}
void Engine::LoseDevice()
{
    if( m_tempD3DDevice != NULL )
        m_tempD3DDevice->Release();

    if( m_mainD3DDevice != NULL )
        m_mainD3DDevice->Release();
}
void Engine::ShutDownInput()
{
    Input::Instance()->Kill();
}
void Engine::LoadAndSetDefaultTexture( const char* path, const char* name )
{
    m_resourceManager->LoadTexture(path, name);
    m_resourceManager->SetDefaultTexture(name);
}
void Engine::PrintLuaMessage(const char* msg)
{
    if(m_currentState)
        m_currentState->HandleMessage(msg);
}
bool Engine::LOpenLuaFile(const char* path, const char* fileName)
{
    //LOL
    if(!LuaManager::Instance()->OpenFile(std::string(std::string(path)+std::string(fileName)).c_str()))
    {
        return LuaManager::Instance()->OpenFile(std::string(std::string("../src/") +
                                                            std::string(path) +
                                                            std::string(fileName)).c_str());
    }
    else
        return true;
}
bool Engine::LLoadSharedMesh( const char* path, const char* fileName )
{
    m_resourceManager->LoadMesh(path, fileName);
    return true; // LOL
}
bool Engine::LLoadTexture( const char* path, const char* fileName )
{
    m_resourceManager->LoadTexture(path, fileName);
    return true; //LOL
}
void Engine::Unregister()
{
    UnregisterClass(m_windowNameWide, m_wind.hInstance );
    delete[] m_windowNameWide;
    delete[] m_windowName;
}
void Engine::ReleaseLuaTables()
{
    for(unsigned int i = 0;i<m_staticLuaObjects.size();++i)
        delete m_staticLuaObjects[i];
}
void Engine::ReleaseResources()
{
    if(m_lineDrawer)
    {
        m_lineDrawer->Release();
        delete m_lineDrawer;
    }

    m_resourceManager->FlushMeshes();
    m_resourceManager->FlushTextures();
    delete m_resourceManager;
    delete m_clock;
    TheTimer::Kill();
    TheServer::Kill();
    TheClient::Kill();
    TheGameMessageFactory::Kill();
}
void Engine::EndCurrentState()
{
    if(m_currentState)
    {
        m_currentState->CleanUp();
        delete m_currentState;
    }
}
void Engine::ResetDevice()
{
    D3DPRESENT_PARAMETERS parameters;
    ZeroMemory( &parameters, sizeof( parameters ) );
    parameters.Windowed = TRUE;
    parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    parameters.BackBufferFormat = D3DFMT_UNKNOWN;
    parameters.EnableAutoDepthStencil = TRUE;
    parameters.AutoDepthStencilFormat = D3DFMT_D16;
    if(m_isDeviceVSYNC)
    {
        /* VSYNC ON */
        parameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
    }
    else
    {
        /* VSYNC OFF */
        parameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    }
    if(m_mainD3DDevice)
    {
        HRESULT hr = m_mainD3DDevice->Reset(&parameters);
        if(hr != S_OK)
        {
            LoseDevice();
            CreateDevice(m_isDeviceVSYNC);
        }
    }
}
